package com.bank.basic.service.impl;

import com.bank.basic.service.TransferService;
import com.bank.basic.util.ClientFactory;
import com.bank.basic.util.EntityFactory;
import com.bank.basic.util.MapperFactory;
import com.bank.basic.util.VoFactory;
import com.bank.common.exceptionUtil.CustomedException;
import com.bank.common.resultUtil.ResultCodeEnum;
import com.bank.common.stringUtil.StringUtil;
import com.bank.model.entity.Account;
import com.bank.model.entity.Transfer;
import com.bank.model.enums.TransferTypeNum;
import com.bank.model.vo.transfer.TransferHistoryVo;
import com.bank.model.vo.transfer.TransferVo;
import com.bank.model.vo.user.UserVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Cejay1314
 * @version 1.0
 * @create 2023/2/17 16:08
 */

@Service
public class TransferServiceImpl implements TransferService {
    @Autowired
    MapperFactory mapperFactory;
    @Autowired
    EntityFactory entityFactory;
    @Autowired
    VoFactory voFactory;
    @Autowired
    ClientFactory clientFactory;

    @Override
    public List<TransferVo> queryListVo(Long userId) {
        List<Account> accounts = clientFactory.getAccountService().getAccounts(userId);
        List<TransferVo> transferVos = new ArrayList<>();
        for (Account account : accounts) {
            transferVos.addAll(queryListVo(account.getAccountId()));
        }
        return transferVos;
    }

    @Override
    public List<Transfer> queryList(String accountId) {
        QueryWrapper<Transfer> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("from_id", accountId);
        queryWrapper.or();
        queryWrapper.eq("to_id", accountId);
        List<Transfer> transfers = mapperFactory.getTransferMapper().selectList(queryWrapper);
        return transfers;
    }

    @Override
    public List<TransferVo> queryListVo(String accountId) {
        List<Transfer> transfers = queryList(accountId);
        List<TransferVo> transferVos = new ArrayList<>();
        for (Transfer transfer : transfers) {
            transferVos.add(voFactory.getTransferVo(transfer, accountId));
        }
        return transferVos;
    }

    @Override
    public List<TransferHistoryVo> queryTransferHistoryVo() {
        List<UserVo> userVos = clientFactory.getListService().getUserVo();
        List<TransferHistoryVo> transferHistoryVos = new ArrayList<>();
        for (UserVo userVo : userVos) {
            List<TransferVo> transferVos = queryListVo(userVo.getId());
            transferHistoryVos.addAll(voFactory.getTransferHistoryVos(userVo, transferVos));
        }
        return transferHistoryVos;
    }

    @Override
    public void addTransfer(TransferVo transferVo) {
        Transfer transfer = entityFactory.getTransfer(transferVo);
        addTransfer(transfer);
    }

    @Override
    public void addTransfer(Transfer transfer) {
        mapperFactory.getTransferMapper().insert(transfer);
        if (transfer.getType() == TransferTypeNum.RealTimeTransfer.getCode()) {
            calculateTransfer(transfer);
        } else if (transfer.getType() == TransferTypeNum.TwoHourTransfer.getCode()) {
            mapperFactory.getScheduledObject().getTwoHourTransfer().add(transfer);
        } else if (transfer.getType() == TransferTypeNum.OnedayTransfer.getCode()) {
            mapperFactory.getScheduledObject().getOneDayTransfer().add(transfer);
        }
    }

    @Override
    public void calculateTransfer(Transfer transfer) {
        Account fromAccount = clientFactory.getAccountService().getAccount(transfer.getFromId().toString());
        Account toAccount = clientFactory.getAccountService().getAccount(transfer.getToId().toString());
        if (fromAccount == null || toAccount == null) {
            throw new CustomedException(ResultCodeEnum.FAIL);
        }
        if (Double.parseDouble(fromAccount.getMoney()) < Double.parseDouble(transfer.getMoney())) {
            throw new CustomedException(ResultCodeEnum.FAIL);
        }
        fromAccount.setMoney(StringUtil.sub(fromAccount.getMoney(), transfer.getMoney()).toString());
        toAccount.setMoney(StringUtil.add(toAccount.getMoney(), transfer.getMoney()).toString());
        clientFactory.getAccountService().updataAccount(fromAccount);
        clientFactory.getAccountService().updataAccount(toAccount);
    }

    @Override
    public void updateTransfer(Transfer transfer) {
        mapperFactory.getTransferMapper().updateById(transfer);
    }

    @Override
    public void delTransfer(Long transferId) {
        mapperFactory.getTransferMapper().deleteById(transferId);
    }
}
